// Copyright Epic Games, Inc. All Rights Reserved.

#include "LyraEquipmentInstance.h"

#include "Components/SkeletalMeshComponent.h"
#include "GameFramework/Character.h"
#include "LyraEquipmentDefinition.h"
#include "Net/UnrealNetwork.h"

#if UE_WITH_IRIS
#include "Iris/ReplicationSystem/ReplicationFragmentUtil.h"
#endif // UE_WITH_IRIS

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraEquipmentInstance)

class FLifetimeProperty;
class UClass;
class USceneComponent;

/**
 * 构造函数
 * @param ObjectInitializer - 对象初始化器
 */
ULyraEquipmentInstance::ULyraEquipmentInstance(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
}

/**
 * 获取世界上下文
 * @return 所属世界对象
 */
UWorld* ULyraEquipmentInstance::GetWorld() const
{
	if (APawn* OwningPawn = GetPawn()) // 获取所属 Pawn
	{
		return OwningPawn->GetWorld(); // 返回 Pawn 的世界
	}
	else
	{
		return nullptr; // 无世界上下文
	}
}

/**
 * 注册生命周期复制属性
 * @param OutLifetimeProps - 输出生命周期属性数组
 */
void ULyraEquipmentInstance::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps); // 调用父类方法

	DOREPLIFETIME(ThisClass, Instigator); // 复制 Instigator
	DOREPLIFETIME(ThisClass, SpawnedActors); // 复制 SpawnedActors
}

#if UE_WITH_IRIS
/**
 * 注册复制片段（Iris 网络系统）
 * @param Context - 片段注册上下文
 * @param RegistrationFlags - 注册标志
 */
void ULyraEquipmentInstance::RegisterReplicationFragments(UE::Net::FFragmentRegistrationContext& Context, UE::Net::EFragmentRegistrationFlags RegistrationFlags)
{
	using namespace UE::Net;

	// 为此对象构建描述符并分配 PropertyReplicationFragments
	FReplicationFragmentUtil::CreateAndRegisterFragmentsForObject(this, Context, RegistrationFlags);
}
#endif // UE_WITH_IRIS

/**
 * 获取所属 Pawn
 * @return 所属 Pawn 对象
 */
APawn* ULyraEquipmentInstance::GetPawn() const
{
	return Cast<APawn>(GetOuter()); // 转换外部对象为 Pawn
}

/**
 * 获取指定类型的 Pawn
 * @param PawnType - Pawn 类型
 * @return 指定类型的 Pawn 对象
 */
APawn* ULyraEquipmentInstance::GetTypedPawn(TSubclassOf<APawn> PawnType) const
{
	APawn* Result = nullptr;
	if (UClass* ActualPawnType = PawnType) // 检查类型有效性
	{
		if (GetOuter()->IsA(ActualPawnType)) // 检查外部对象类型匹配
		{
			Result = Cast<APawn>(GetOuter()); // 转换外部对象为 Pawn
		}
	}
	return Result; // 返回结果
}

/**
 * 生成装备演员
 * @param ActorsToSpawn - 要生成的演员信息数组
 */
void ULyraEquipmentInstance::SpawnEquipmentActors(const TArray<FLyraEquipmentActorToSpawn>& ActorsToSpawn)
{
	if (APawn* OwningPawn = GetPawn()) // 获取所属 Pawn
	{
		USceneComponent* AttachTarget = OwningPawn->GetRootComponent(); // 默认附加目标为根组件
		if (ACharacter* Char = Cast<ACharacter>(OwningPawn)) // 如果是角色类
		{
			AttachTarget = Char->GetMesh(); // 使用角色网格体作为附加目标
		}

		for (const FLyraEquipmentActorToSpawn& SpawnInfo : ActorsToSpawn) // 遍历要生成的演员信息
		{
			AActor* NewActor = GetWorld()->SpawnActorDeferred<AActor>(SpawnInfo.ActorToSpawn, FTransform::Identity, OwningPawn); // 延迟生成演员
			NewActor->FinishSpawning(FTransform::Identity, /*bIsDefaultTransform=*/ true); // 完成生成
			NewActor->SetActorRelativeTransform(SpawnInfo.AttachTransform); // 设置相对变换
			NewActor->AttachToComponent(AttachTarget, FAttachmentTransformRules::KeepRelativeTransform, SpawnInfo.AttachSocket); // 附加到目标组件

			SpawnedActors.Add(NewActor); // 添加到已生成演员列表
		}
	}
}

/**
 * 销毁装备演员
 */
void ULyraEquipmentInstance::DestroyEquipmentActors()
{
	for (AActor* Actor : SpawnedActors) // 遍历已生成演员
	{
		if (Actor) // 检查演员有效性
		{
			Actor->Destroy(); // 销毁演员
		}
	}
}

/**
 * 装备时调用
 */
void ULyraEquipmentInstance::OnEquipped()
{
	K2_OnEquipped(); // 调用蓝图事件
}

/**
 * 卸下时调用
 */
void ULyraEquipmentInstance::OnUnequipped()
{
	K2_OnUnequipped(); // 调用蓝图事件
}

/**
 * 复制通知：Instigator
 */
void ULyraEquipmentInstance::OnRep_Instigator()
{
}